package io.renren.utils;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import io.renren.model.JsonObjectModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.*;

/**
 * @Description: Json 工具类
 * @Classname: org.springblade.composer.utils.JsonUtils
 * @Author: FanH
 * @Create: 2024/1/13 17:09
 */
public class JsonUtils {
    private static final Logger logger = LoggerFactory.getLogger(JsonUtils.class);

    public static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();

    public static void removeNullAndEmptyStrings(JsonNode node) {
        if (node instanceof ObjectNode) {
            for (Iterator<Map.Entry<String, JsonNode>> it = node.fields(); it.hasNext(); ) {
                Map.Entry<String, JsonNode> entry = it.next();

                // 判断当前属性是否为null或空字符串
                if (entry.getValue().isNull() || ("\"\"").equals(entry.getValue().toString())
                        || ("[]").equals(entry.getValue().toString()) || ("{}").equals(entry.getValue().toString())) {
                    it.remove();
                } else {
                    removeNullAndEmptyStrings(entry.getValue());
                }
            }
        } else if (node instanceof ArrayNode) {
            for (int i = 0; i < node.size(); ++i) {
                removeNullAndEmptyStrings(node.get(i));
            }
        }
    }

//    /**
//     * 通过json转java类
//     */
//    public static void productJsonToJava(String jsonBody, String packageName, String suffix) throws JsonProcessingException {
//        parsingJson(OBJECT_MAPPER.readTree(jsonBody), packageName, "L3vpnOne", suffix);
//    }


    /**
     * 1. 解析json
     * 1.1 解析json路径
     * 1.2 解析json param
     * 2. 构建基础类(当前类存在，当前类不存在)
     * 3. 将json解析的参数填入到基础类中
     */
    public static void parsingJsonToModel(String drive, String parentPath, String jsonName, String suffix, String json) throws IOException {
        JsonNode jsonNode = OBJECT_MAPPER.readTree(json);
        List<JsonObjectModel> jsonObjectList = new ArrayList<>();
        parsingSingleJson(parentPath, jsonName, suffix, jsonNode, jsonObjectList);

        for (JsonObjectModel model : jsonObjectList) {
            File javaFile = createJavaFile(parsingClassName(model.getJsonName()), drive, parsingPackageToPath(model.getJsonPath()), suffix);
            if (!javaFile.exists()) {
                // 创建当前文件
                if (!javaFile.getParentFile().exists() && !javaFile.getParentFile().mkdirs()) {
                    logger.error("create file path error.");
                    throw new RuntimeException("创建文件夹失败！");
                }

                javaFile.createNewFile();
            }

            // 构建基础类
            StringBuilder content = buildBaseModelClass(parsingPackageName(model.getJsonPath()), parsingClassName(model.getJsonName()),
                    suffix, model.getImportPackages());

            // 将参数写入到基础类中
            completeModelClass(content, model.getJsonParams());

            // 将java内容写入到java file中
            writeContentToJavaFile(content.toString(), javaFile);
        }
    }

    /**
     * 将内容写入到文件中
     */
    public static void writeContentToJavaFile(String content, File file) throws IOException {
        Files.write(file.toPath(), content.getBytes());
    }

    /**
     * 通过json model创建java文件
     */
    public static File createJavaFile(String fileName, String drive, String filePath, String suffix) {
        return new File(drive + filePath, fileName + suffix + ".java");
    }

    public static String parsingSingleJson(String parentPath, String jsonName, String suffix,
                                           JsonNode jsonNode, List<JsonObjectModel> jsonObjectList) {
        JsonObjectModel jsonObjectModel = new JsonObjectModel();
        jsonObjectModel.setJsonPath(parentPath);
        jsonObjectModel.setJsonName(jsonName);


        // 解析当前节点的子节点参数
        List<String> importPackages = new ArrayList<>();
        Map<String, String> paramMap = new HashMap<>();
        if (jsonNode.isArray()){
            jsonNode = jsonNode.get(0);
        }
        for (Iterator<Map.Entry<String, JsonNode>> it = jsonNode.fields(); it.hasNext(); ) {
            Map.Entry<String, JsonNode> entry = it.next();
            String paramName = entry.getKey();

            String paramType;
            JsonNode value = entry.getValue();
            if (value.isInt()) {
                paramType = "Integer";
            } else if (value.isTextual()) {
                paramType = "String";
            } else if (value.isBoolean()) {
                paramType = "Boolean";
            } else if (value.isDouble()) {
                paramType = "Double";
            } else if (value.isShort()) {
                paramType = "Short";
            } else if (value.isFloat()) {
                paramType = "Float";
            } else if (value.isLong()) {
                paramType = "Long";
            } else if (value.isArray()) {
                paramType = "List<" + parsingClassName(entry.getKey()) + suffix + ">";
                importPackages.add("java.util.List");

                // 应该返回子类的package+ClassName
                String importPackage = parsingSingleJson(parentPath + "." + parsingPackageName(jsonName), entry.getKey(), suffix,
                        value, jsonObjectList);
                importPackages.add(importPackage);
            } else if (value.isObject()) {
                paramType = parsingClassName(entry.getKey()) + suffix;

                // 应该返回子类的package+ClassName
                String importPackage = parsingSingleJson(parentPath + "." + parsingPackageName(jsonName), entry.getKey(), suffix,
                        value, jsonObjectList);
                importPackages.add(importPackage);
            } else if (value.isNull()) {
                paramType = "String";
            } else {
                logger.error("Error parsing JSON, not matching the current parameter type：{}", value.getClass().getName());
                throw new RuntimeException(entry.getKey());
            }

            paramMap.put(paramName, paramType);
        }
        jsonObjectModel.setImportPackages(importPackages);
        jsonObjectModel.setJsonParams(paramMap);
        jsonObjectList.add(jsonObjectModel);

        return parsingPackageName(parentPath) + "." + parsingClassName(jsonName) + suffix;
    }

    /**
     * 构建json基础类
     */
    public static StringBuilder buildBaseModelClass(String packageName, String className, String suffix, List<String> importPackages) {
        StringBuilder builder = new StringBuilder();
        builder.append("package ").append(packageName).append(";").append("\n\n");
        builder.append("import ").append("com.fasterxml.jackson.annotation.JsonIgnoreProperties;").append("\n");
        builder.append("import ").append("com.fasterxml.jackson.annotation.JsonInclude;").append("\n");
        builder.append("import ").append("com.fasterxml.jackson.annotation.JsonProperty;").append("\n");
        for (String importPackage : importPackages) {
            builder.append("import ").append(importPackage).append(";\n");
        }


        builder.append("import ").append("lombok.Data;").append("\n");
        builder.append("import ").append("java.io.Serializable;").append("\n\n");

        builder.append("@Data").append("\n");
        builder.append("@JsonIgnoreProperties(ignoreUnknown = true)").append("\n");
        builder.append("@JsonInclude(JsonInclude.Include.NON_NULL)").append("\n");
        builder.append("public class ").append(className).append(suffix).append(" implements Serializable {").append("\n");
        builder.append("\tprivate static final long serialVersionUID = 1L;").append("\n\n");

        return builder;
    }

    /**
     * 将json参数赋值到基础类上
     */
    public static void completeModelClass(StringBuilder jsonBuilder, Map<String, String> jsonParam) {
        for (Map.Entry<String, String> entry : jsonParam.entrySet()) {
            jsonBuilder.append("\t@JsonProperty(\"").append(entry.getKey()).append("\")").append("\n");
            jsonBuilder.append("\tprivate ").append(entry.getValue()).append(" ").append(parsingParamName(entry.getKey())).append(";\n\n");
        }
        jsonBuilder.append("}");
    }

//    /**
//     * 解析json
//     */
//    public static void parsingJson(JsonNode node, String packageName, String className, String suffix) {
//        StringBuilder builder = new StringBuilder();
//        builder.append("package ").append(packageName).append(";").append("\n\n");
//        builder.append("import ").append("com.fasterxml.jackson.annotation.JsonIgnoreProperties;").append("\n");
//        builder.append("import ").append("com.fasterxml.jackson.annotation.JsonInclude;").append("\n");
//        builder.append("import ").append("com.fasterxml.jackson.annotation.JsonIgnoreProperties;").append("\n");
//        builder.append("import ").append("com.fasterxml.jackson.annotation.JsonInclude;").append("\n");
//        builder.append("import ").append("com.fasterxml.jackson.annotation.JsonProperty;").append("\n");
//
//
//        builder.append("import ").append("lombok.Data;").append("\n");
//        builder.append("import ").append("java.io.Serializable;").append("\n\n");
//
//        builder.append("@Data").append("\n");
//        builder.append("@JsonIgnoreProperties(ignoreUnknown = true)").append("\n");
//        builder.append("@JsonInclude(JsonInclude.Include.NON_NULL)").append("\n");
//        builder.append("public class ").append(className).append(suffix).append(" implements Serializable {").append("\n");
//        builder.append("\tprivate static final long serialVersionUID = 1L;").append("\n\n");
//
//        if (node instanceof ObjectNode) {
//            parsingJsonObject(builder, node, packageName, suffix);
//        } else if (node instanceof ArrayNode) {
//            parsingJsonArray(node, packageName, className, suffix);
//        }
//
//        builder.append("}");
//        String filePath = "D:/l3vpn/" + className + suffix + ".java"; // 替换为你的文件路径
//        try {
//            Files.write(Paths.get(filePath), builder.toString().getBytes());
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
//    }
//
//    public static void parsingJsonObject(StringBuilder builder, JsonNode jsonNode, String packageName, String suffix) {
//
//        for (Iterator<Map.Entry<String, JsonNode>> it = jsonNode.fields(); it.hasNext(); ) {
//            Map.Entry<String, JsonNode> entry = it.next();
//
//            builder.append("\t@JsonProperty(\"").append(entry.getKey()).append("\")").append("\n");
//
//            JsonNode value = entry.getValue();
//            if (value.isInt()) {
//                builder.append("\tprivate ").append("Integer ").append(parsingParamName(entry.getKey())).append(";\n\n");
//            } else if (value.isTextual()) {
//                builder.append("\tprivate ").append("String ").append(parsingParamName(entry.getKey())).append(";\n\n");
//            } else if (value.isBoolean()) {
//                builder.append("\tprivate ").append("Boolean ").append(parsingParamName(entry.getKey())).append(";\n\n");
//            } else if (value.isDouble()) {
//                builder.append("\tprivate ").append("Double ").append(parsingParamName(entry.getKey())).append(";\n\n");
//            } else if (value.isShort()) {
//                builder.append("\tprivate ").append("Short ").append(parsingParamName(entry.getKey())).append(";\n\n");
//            } else if (value.isFloat()) {
//                builder.append("\tprivate ").append("Float ").append(parsingParamName(entry.getKey())).append(";\n\n");
//            } else if (value.isLong()) {
//                builder.append("\tprivate ").append("Long ").append(parsingParamName(entry.getKey())).append(";\n\n");
//            } else if (value.isArray()) {
//                builder.append("\tprivate List<").append(parsingClassName(entry.getKey())).append(suffix).append("> ")
//                        .append(parsingParamName(entry.getKey())).append(";\n\n");
//
//                parsingJsonArray(value, packageName, parsingClassName(entry.getKey()), suffix);
//            } else if (value.isObject()) {
//                builder.append("\tprivate ").append(parsingClassName(entry.getKey())).append(suffix).append(" ")
//                        .append(parsingParamName(entry.getKey())).append(";\n\n");
//
//                parsingJson(value, packageName, parsingClassName(entry.getKey()), suffix);
//            } else if (value.isNull()) {
//                builder.append("\tprivate ").append("String ").append(parsingParamName(entry.getKey())).append(";\n\n");
//            } else {
//                throw new RuntimeException(entry.getKey());
//            }
//        }
//    }
//
//    private static void parsingJsonArray(JsonNode jsonNode, String packageName, String className, String suffix) {
//        ArrayNode arrayNode = (ArrayNode) jsonNode;
//        if (!arrayNode.isEmpty()) {
//            parsingJson(arrayNode.get(0), packageName, className, suffix);
//        }
//    }

    private static String parsingClassName(String name) {
        name = name.substring(name.lastIndexOf(":") + 1);
        name = name.toLowerCase();
        StringBuilder camelCase = new StringBuilder();
        boolean capitalizeNext = false;
        boolean isFirst = true;
        for (int i = 0; i < name.length(); i++) {
            char c = name.charAt(i);
            if (isFirst) {
                camelCase.append(Character.toUpperCase(c));
                isFirst = false;
            } else {
                if (c == '-') {
                    capitalizeNext = true;
                } else if (capitalizeNext) {
                    camelCase.append(Character.toUpperCase(c));
                    capitalizeNext = false;
                } else {
                    camelCase.append(Character.toLowerCase(c));
                }
            }
        }
        return camelCase.toString();
    }

    private static String parsingParamName(String name) {
        name = name.substring(name.lastIndexOf(":") + 1);
        name = name.toLowerCase();
        StringBuilder camelCase = new StringBuilder();
        boolean capitalizeNext = false;
        for (int i = 0; i < name.length(); i++) {
            char c = name.charAt(i);
            if (c == '-') {
                capitalizeNext = true;
            } else if (capitalizeNext) {
                camelCase.append(Character.toUpperCase(c));
                capitalizeNext = false;
            } else {
                camelCase.append(Character.toLowerCase(c));
            }
        }
        return camelCase.toString();
    }

    private static String parsingPackageName(String name) {
        name = name.substring(name.lastIndexOf(":") + 1);
        name = name.toLowerCase();
        return name.replace("-", "_");
    }

    private static String parsingPackageToPath(String packageName) {
        return packageName.replace(".", File.separator);
    }
}
